package com.javalong.affairs.base.common;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;

public class UIHandler {

    private Handler handlerThread;
    private Handler handler;
    private SparseArray<List<ISynCallback>> mapCallback;

    private Integer nFlag = 10000;

    public UIHandler() {
        mapCallback = new SparseArray<List<ISynCallback>>();
        HandlerThread thread = new HandlerThread("thread");
        thread.start();
        Handler.Callback callback = new Handler.Callback() {

            @Override
            public boolean handleMessage(Message arg0) {
                Log.v("test", "sync:" + Thread.currentThread().getName() + ":"
                        + arg0.what);
                Bundle param = (Bundle) arg0.obj;
                if (mapCallback.indexOfKey(arg0.what) >= 0) {
                    List<ISynCallback> list = mapCallback.get(arg0.what);
                    Log.v("test", "sync:" + Thread.currentThread().getName()
                            + ":" + list);
                    if (list != null) {
                        for (ISynCallback callback : list) {
                            if (callback != null)
                                callback.OnSynCalled(arg0.what, param);
                        }
                    }
                }
                return false;
            }

            ;
        };
        handler = new Handler(callback);
        handlerThread = new Handler(thread.getLooper(), callback);
    }

    public void registerCallback(ISynCallback pCallback, int pulId) {
        List<ISynCallback> list = null;
        if (mapCallback.indexOfKey(pulId) > 0) {
            list = mapCallback.get(pulId);
            if (!list.contains(pCallback)) {
                list.add(pCallback);
            }
        } else {
            list = new ArrayList<ISynCallback>();
            list.add(pCallback);
            mapCallback.put(pulId, list);
        }
    }

    public void unRegisterCallback(ISynCallback pCallback, int ulId) {
        if (mapCallback.indexOfKey(ulId) != -1) {
            List<ISynCallback> list = mapCallback.get(ulId);
            if (list != null) {
                if (pCallback != null) {
                    list.remove(pCallback);
                }
                if (list.isEmpty()) {
                    mapCallback.remove(ulId);
                }
            }
        }
    }

    public void unRegisterCallback(int ulId) {
        if (mapCallback.indexOfKey(ulId) >= 0) {
            mapCallback.get(ulId).clear();
            mapCallback.remove(ulId);
        }
    }

    public void postCallback(int ulId, Bundle param) {
        final Message msg = new Message();
        msg.what = ulId;
        msg.obj = param;
        handler.post(new Runnable() {
            @Override
            public void run() {
                handler.dispatchMessage(msg);
            }
        });
    }

    public void post(Runnable r) {
        handler.post(r);
    }

    public void postDelayed(Runnable r, long delayMillis) {
        handler.postDelayed(r, delayMillis);
    }

    public void sendCallback(int ulId, Bundle param) {
        Message msg = new Message();
        msg.what = ulId;
        msg.obj = param;
        handler.sendMessage(msg);
    }

    public class SimpleSynCallback implements ISynCallback {
        private Runnable action;

        public SimpleSynCallback(Runnable action) {
            this.action = action;
        }

        public void OnSynCalled(int ulID, Bundle param) {
            if (action != null) {
                action.run();
            }
            unRegisterCallback(ulID);
        }
    }

    public void postCallbackThread(int ulId, Bundle param) {
        final Message msg = new Message();
        msg.what = ulId;
        msg.obj = param;
        handlerThread.post(new Runnable() {
            @Override
            public void run() {
                handlerThread.dispatchMessage(msg);
            }
        });
    }

    public void postThread(Runnable r) {
        handlerThread.post(r);
    }

    public void postDelayedThread(Runnable r, long delayMillis) {
        handlerThread.postDelayed(r, delayMillis);
    }

    public void sendCallbackThread(int ulId, Bundle param) {
        Message msg = new Message();
        msg.what = ulId;
        msg.obj = param;
        handlerThread.sendMessage(msg);
    }

    public void runOnUiThread(Runnable action) {
        SimpleSynCallback callBack = new SimpleSynCallback(action);
        nFlag++;
        this.registerCallback(callBack, nFlag);
        this.sendCallback(nFlag, null);
    }
}